package service.impl;

import java.math.RoundingMode;
import java.util.Date;

import models.Pay;
import prefix.util.DateUtil;
import prefix.util.OverallUtil;
import processor.PayProcessor;
import service.PayService;
import service.exception.PayException;

public class PayServiceImpl implements PayService {

    protected Pay dbpay;

    public PayServiceImpl() {
        this.dbpay = new Pay();
    }

    public PayServiceImpl(Pay pay) {
        this.dbpay = pay;
    }

    @Override
    public PayProcessor getProcessor() {
        // TODO Auto-generated method stub
        return new PayProcessor(this.dbpay);
    }

    public void validateForNotify() {

    }

    public void validateForPull() throws PayException {
        validateDateAndAmount();
        if (!OverallUtil.isIn(this.dbpay.getStatus(), Pay.Status.FUTURE, Pay.Status.NOTIFIED)) {
            throw new PayException(PayException.CODE.INVALID_STATUS_FOR_PULL);
        }

        Date pullDate = DateUtil.normalizeDay(this.dbpay.getPullD());
        Date dueDate = DateUtil.normalizeDay(this.dbpay.getDueD());
        Date now = DateUtil.normalizeDay(new Date());

        if (now.before(pullDate) && now.before(dueDate))
            throw new PayException(PayException.CODE.TOO_EARLY_TO_PULL);
    }

    public void validateForProcessing() throws PayException {
        validateDateAndAmount();
        Date dueDate = DateUtil.normalizeDay(this.dbpay.getDueD());
        Date now = DateUtil.normalizeDay(new Date());

        if (now.before(dueDate))
            throw new PayException(PayException.CODE.TOO_EARLY_TO_PROCESS);
    }

    public void validateDateAndAmount() throws PayException {
        double pullAmnt = this.dbpay.getPullAmount();
        Date pullDate = this.dbpay.getPullD();

        double dueAmnt = this.dbpay.getDueAmount();
        Date dueDate = this.dbpay.getDueD();

        if (dueAmnt <= 0 || dueDate == null)
            throw new PayException(PayException.CODE.INVALID_DUE_DATE_OR_AMOUNT);

        if (pullAmnt <= 0 || pullDate == null)
            throw new PayException(PayException.CODE.INVALID_PULL_DATE_OR_AMOUNT);

    }

    public double getAmountToBeCurrent() {
        double dueAmount = this.dbpay.getIntAccr() + dbpay.getLateFeeAccr() + dbpay.getPrncpAccr()
                + dbpay.getManagementFeeAccr() - this.dbpay.getIntPaid() - this.dbpay.getLateFeePaid()
                - this.dbpay.getPrncpPaid() - this.dbpay.getManagementFeePaid();
        dueAmount = OverallUtil.round2Decimal(dueAmount, RoundingMode.CEILING).doubleValue();
        return dueAmount;
    }
}
